// HSS.Data.Guard.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       Guard.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
namespace HSS.Data
{
	#region Using Directives
	using System;
	using System.Globalization;
	#endregion

	/// <summary>
	/// Guard is an Exception helper for throwing errors if arguments are not valid.
	/// </summary>
	internal static class Guard
	{
		/// <summary>
		/// Throws <see cref="ArgumentNullException"/> if the given argument is null.
		/// </summary>
		/// <exception cref="ArgumentNullException">Thrown if the tested value is null.</exception>
		/// <param name="argumentValue">Argument value to test.</param>
		/// <param name="argumentName">Name of the argument being tested.</param>
		public static void ArgumentNotNull(object argumentValue, string argumentName)
		{
			if (argumentValue == null) throw new ArgumentNullException(argumentName);
		}
		/// <summary>
		/// Throws an exception if the tested string argument is null or the empty string.
		/// </summary>
		/// <exception cref="ArgumentNullException">Thrown if the string value is null.</exception>
		/// <exception cref="ArgumentException">Thrown if the string is empty</exception>
		/// <param name="argumentValue">Argument value to check.</param>
		/// <param name="argumentName">Name of argument being checked.</param>
		public static void ArgumentNotNullOrEmpty(string argumentValue, string argumentName)
		{
			if (argumentValue == null) throw new ArgumentNullException(argumentName);
			if (argumentValue.Length == 0) throw new ArgumentException("The provided string argument must not be empty.", argumentName);
		}
		/// <summary>
		/// Throws an exception if the tested argument is null or not serializable.
		/// </summary>
		/// <exception cref="ArgumentNullException">Thrown if the tested value is null.</exception>
		/// <exception cref="ArgumentException">Thrown if the tested value is not serializable.</exception>
		/// <param name="argumentValue">Argument value to test.</param>
		/// <param name="argumentName">Name of the argument being tested.</param>
		public static void ArgumentIsSerializable(object argumentValue, string argumentName)
		{
			if (argumentValue == null) throw new ArgumentNullException(argumentName);
			Type objType = argumentValue.GetType();
			if (!objType.IsSerializable)
				throw new ArgumentException("value must be serializable.");
		}
		/// <summary>
		/// Verifies that an argument instance is assignable from the provided type (meaning
		/// interfaces are implemented, or classes exist in the base class hierarchy, or instance can be 
		/// assigned through a runtime wrapper, as is the case for COM Objects).
		/// </summary>
		/// <param name="assignmentTargetType">The argument type that will be assigned to.</param>
		/// <param name="assignmentInstance">The instance that will be assigned.</param>
		/// <param name="argumentName">Argument name.</param>
		public static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName)
		{
			if (assignmentInstance == null) throw new ArgumentNullException("assignmentInstance");
			Type assignmentType = assignmentInstance.GetType();
			Guard.TypeIsAssignable(assignmentTargetType, assignmentType, argumentName);
		}
		/// <summary>
		/// Verifies that an argument type is assignable from the provided type (meaning
		/// interfaces are implemented, or classes exist in the base class hierarchy).
		/// </summary>
		/// <param name="assignmentTargetType">The argument type that will be assigned to.</param>
		/// <param name="assignmentValueType">The type of the value being assigned.</param>
		/// <param name="argumentName">Argument name.</param>
		public static void TypeIsAssignable(Type assignmentTargetType, Type assignmentValueType, string argumentName)
		{
			if (assignmentTargetType == null) throw new ArgumentNullException("assignmentTargetType");
			if (assignmentValueType == null) throw new ArgumentNullException("assignmentValueType");

			if (!assignmentTargetType.IsAssignableFrom(assignmentValueType))
			{
				throw new ArgumentException(string.Format(
					CultureInfo.CurrentCulture,
					"The type {1} cannot be assigned to variables of type {0}.",
					assignmentTargetType,
					assignmentValueType),
					argumentName);
			}
		}
	}
}